package com.xuecheng.api.content.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.xuecheng.api.common.domain.code.CommonErrorCode;
import com.xuecheng.api.common.enums.common.CommonEnum;
import com.xuecheng.api.common.exception.ExceptionCast;
import com.xuecheng.api.content.common.constant.ContentErrorCode;
import com.xuecheng.api.content.convert.CourseBaseConvert;
import com.xuecheng.api.content.entity.CourseMarket;
import com.xuecheng.api.content.mapper.CourseBaseMapper;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.service.CourseBaseService;
import com.xuecheng.api.content.service.CourseMarketService;
import com.xuecheng.api.common.domain.page.PageRequestParams;
import com.xuecheng.api.common.domain.page.PageVO;
import com.xuecheng.api.common.enums.content.CourseAuditEnum;
import com.xuecheng.api.common.enums.content.CourseChargeEnum;
import com.xuecheng.api.common.util.StringUtil;
import com.xuecheng.api.content.entity.CourseBase;
import com.xuecheng.api.content.model.qo.QueryCourseModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

    @Autowired
    private CourseMarketService courseMarketService;
    /*
    * 步骤分析：
    *  1.是否需要开启事务
    *  2.判断关键数据
    *       分页数据
    *       查询条件
    *  3.构建mp分页对象
    *  4.构建查询条件对象LambdaQueryWrapper
    *  5.查询数据
    *  6.获得数据并封装返回结果
    *       封装PageVo数据
    * */
    public PageVO queryCourseList(PageRequestParams params, QueryCourseModel model, Long companyId) {

        // 1.判断关键数据（分页数据）
        if (params.getPageNo() < 1) {
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (params.getPageSize() < 1) {
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }

        // 2.构建mp的分页对象-设置当前页和每页条数
        Page<CourseBase> page = new Page<>(params.getPageNo(), params.getPageSize());
        // 3.构建查询条件
        //    课程名称：like查询
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtil.isNotBlank(model.getCourseName()),CourseBase::getName, model.getCourseName());
        queryWrapper.eq(StringUtil.isNotBlank(model.getAuditStatus()),CourseBase::getAuditStatus, model.getAuditStatus());
        queryWrapper.eq(CourseBase::getCompanyId, companyId);
        // 4.查询数据
        Page<CourseBase> pageResult = this.page(page, queryWrapper);
        long total = pageResult.getTotal();
        List<CourseBase> records = pageResult.getRecords();
        List<CourseBaseDTO> dtos = Collections.EMPTY_LIST;
        if (!(CollectionUtils.isEmpty(records))) {
            dtos = CourseBaseConvert.INSTANCE.entitys2dtos(records);
        }
        // 5.封装查询后的结果
        PageVO pageVO = new PageVO(dtos, total, params.getPageNo(), params.getPageSize());
        return pageVO;
    }

    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO dto) {
        //1.先判断前端传来的关键数据是否有问题
        verifyCourseBase(dto);
        //2.将dto转为po数据
        CourseBase courseBase=CourseBaseConvert.INSTANCE.dto2entity(dto);
        //后端数据更新
        courseBase.setStatus(null);
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
        courseBase.setId(null);
        boolean baseResult = this.save(courseBase);
        if(!baseResult){
            throw new RuntimeException("课程基础信息保存失败");
        }
        //保存课程营销信息数据并判断保存后的结果--后操作，CourseMarket中需要管理CourseBaseId
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())) {
            courseMarket.setPrice(dto.getPrice().floatValue());
        }
        boolean marketResult = courseMarketService.save(courseMarket);
        if (!marketResult) {
            throw new RuntimeException("课程营销保存失败");
        }

        //3.将数据库的最新数据返回给前端
        CourseBase po = this.getById(courseBase.getId());
        CourseBaseDTO reultDTO = CourseBaseConvert.INSTANCE.entity2dto(po);
        reultDTO.setPrice(dto.getPrice());
        reultDTO.setCharge(dto.getCharge());
        return reultDTO;
    }


    public CourseBaseDTO getCourseBaseById(Long courseBaseId, Long companyId) {
        if (ObjectUtils.isEmpty(courseBaseId)||
                ObjectUtils.isEmpty(companyId)
        ) {
            throw new RuntimeException("传入参数和接口不匹配");
        }
        CourseBase courseBase = getCourseByBaseId(courseBaseId, companyId);
        // 3.将po数据转为dto并返回
        //  courseBase
        //  courseMarket
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2dto(courseBase);
        //     课程营销
        CourseMarket courseMarket = getCourseMarketByCourseId(courseBaseId);

        courseBaseDTO.setCharge(courseMarket.getCharge());
        courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice().toString()));

        return courseBaseDTO;
    }

    @Transactional
    public CourseBaseDTO modifyCourseBaseById(CourseBaseDTO dto) {

        //1.判断关键数据
        //  可以直接调用添加时对关键数据的判断
        //  判断课程的id不能为空
        verifyCourseMsg(dto);

        Long courseBaseId = dto.getCourseBaseId();
        if (ObjectUtils.isEmpty(courseBaseId)) {
            throw new RuntimeException("修改课程id不能为空");
        }

        // 2.判断业务数据
        //   课程基础信息
        //     判断是否存在
        //     判断是否是同一家教学机构
        //     判断是否删除
        //     判断课程审核状态
        //        未提交和审核未通过才可以进行修改
        //   课程营销（根据courseid）
        getCourseByLogic(dto.getCompanyId(), courseBaseId);

        //     课程营销
        CourseMarket courseMarket = getCourseMarketByCourseId(courseBaseId);


        // 3.修改数据
        //   修改课程基础信息数据
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getName, dto.getName());
        updateWrapper.set(CourseBase::getTags, dto.getTags());
        updateWrapper.set(CourseBase::getMt, dto.getMt());
        updateWrapper.set(CourseBase::getSt, dto.getSt());
        updateWrapper.set(CourseBase::getDescription, dto.getDescription());
        updateWrapper.set(CourseBase::getUsers, dto.getUsers());
        updateWrapper.set(CourseBase::getPic, dto.getPic());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());

        updateWrapper.eq(CourseBase::getId, dto.getCourseBaseId());


        boolean baseResult = this.update(updateWrapper);

        if (!baseResult) {
            throw new RuntimeException("课程信息修改失败");
        }

        //     课程营销数据表
        //         charge price
        // 如果使用mq修改一张表中的极个别数据，UpdateWrapper
        // update course_market set charge=xxx,price=xxx  where courseid=xx
        LambdaUpdateWrapper<CourseMarket> marketUpdateWrapper = new LambdaUpdateWrapper<>();
        marketUpdateWrapper.set(CourseMarket::getCharge,dto.getCharge());

        String charge = dto.getCharge();
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(charge)) {

            BigDecimal price = dto.getPrice();
            if (ObjectUtils.isEmpty(price)) {
                throw new RuntimeException("收费课程价格不能为空");
            }

            marketUpdateWrapper.set(CourseMarket::getPrice, dto.getPrice().floatValue());
        } else {
            // 如果课程为免费，需要价格赋值为0
            marketUpdateWrapper.set(CourseMarket::getPrice, 0F);
        }
        marketUpdateWrapper.eq(CourseMarket::getCourseId, courseBaseId);


        boolean marketResult = courseMarketService.update(marketUpdateWrapper);

        //      修改数据时要判断修改后结果
        if (!marketResult) {
            throw new RuntimeException("修改课程营销数据失败");
        }


        // 4.将修改后的最新数据返回给前端
        CourseBaseDTO resultDTO = getLastCourseBaseDTO(dto, courseBaseId);

        return resultDTO;
    }






    public CourseBase getCourseByBaseId(Long courseBaseId, Long companyId) {
        // select * from course_base where id = ? and companyId = ?
        LambdaQueryWrapper<CourseBase> baseQueryWrapper = new LambdaQueryWrapper<>();
        baseQueryWrapper.eq(CourseBase::getId, courseBaseId);
        baseQueryWrapper.eq(CourseBase::getCompanyId, companyId);
        // baseQueryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCodeInt());

        CourseBase courseBase = this.getOne(baseQueryWrapper);

        if (ObjectUtils.isEmpty(courseBase)) {
            throw new RuntimeException("课程不存在");
        }

        Integer status = courseBase.getStatus();
        if (!(CommonEnum.USING_FLAG.getCodeInt().equals(status))) {
            throw new RuntimeException("课程信息已经被删除");
        }
        return courseBase;
    }
    private CourseMarket getCourseMarketByCourseId(Long courseBaseId) {
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);

        CourseMarket courseMarket = courseMarketService.getOne(marketQueryWrapper);

        if (ObjectUtils.isEmpty(courseMarket)) {
            throw new RuntimeException("课程营销数据不存在");
        }
        return courseMarket;
    }

    private void verifyCourseBase(CourseBaseDTO dto) {
        if(ObjectUtils.isEmpty(dto.getCompanyId())){
            throw new RuntimeException("公司id不能为空");
        }
        if(StringUtil.isBlank(dto.getName())){
            throw new RuntimeException("公司id不能为空");
        }
        if (StringUtil.isBlank(dto.getName())) {
            throw new RuntimeException("课程名称不能为空");
        }
        if (StringUtil.isBlank(dto.getMt())) {
            throw new RuntimeException("课程大分类不能为空");
        }
        if (StringUtil.isBlank(dto.getSt())) {
            throw new RuntimeException("课程小分类不能为空");
        }
        if (StringUtil.isBlank(dto.getGrade())) {
            throw new RuntimeException("课程等级不能为空");
        }
        if (StringUtil.isBlank(dto.getTeachmode())) {
            throw new RuntimeException("课程教学模式不能为空");
        }
        if (StringUtil.isBlank(dto.getUsers())) {
            throw new RuntimeException("使用人群不能为空");
        }
        if (StringUtil.isBlank(dto.getCharge())) {
            throw new RuntimeException("课程收费不能为空");
        }
        String charge=dto.getCharge();
        if(CourseChargeEnum.CHARGE_YES.getCode().equals(charge)){
            if(ObjectUtils.isEmpty(dto.getPrice())){
                throw new RuntimeException("收费课程的价格不能位空");
            }
        }else {
            dto.setPrice(new BigDecimal("0"));
        }
    }
    private void verifyCourseMsg(CourseBaseDTO dto) {
        if (ObjectUtils.isEmpty(dto.getCompanyId())) {
            ExceptionCast.cast(ContentErrorCode.E_120018);
        }

        if (StringUtil.isBlank(dto.getName())) {
            ExceptionCast.cast(ContentErrorCode.E_120004);
        }

        if (StringUtil.isBlank(dto.getMt())) {
            ExceptionCast.cast(ContentErrorCode.E_120002);
        }

        if (StringUtil.isBlank(dto.getSt())) {
            ExceptionCast.cast(ContentErrorCode.E_120003);
        }

        if (StringUtil.isBlank(dto.getGrade())) {
            ExceptionCast.cast(ContentErrorCode.E_120007);
        }

        if (StringUtil.isBlank(dto.getTeachmode())) {
            ExceptionCast.cast(ContentErrorCode.E_120006);
        }

        if (StringUtil.isBlank(dto.getUsers())) {
            ExceptionCast.cast(ContentErrorCode.E_120019);
        }

        if (StringUtil.isBlank(dto.getCharge())) {
            ExceptionCast.cast(ContentErrorCode.E_120020);
        }
    }
    private void getCourseByLogic(Long companyId, Long courseBaseId) {

        CourseBase courseBase = getCourseByBaseId(courseBaseId, companyId);

        String auditStatus = courseBase.getAuditStatus();
        if (CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(auditStatus)||
                CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(auditStatus)
        ) {
            throw new RuntimeException("课程审核状态异常");
        }
    }

    private CourseBaseDTO getLastCourseBaseDTO(CourseBaseDTO dto, Long id) {
        CourseBase po = this.getById(id);

        CourseBaseDTO resultDTO = CourseBaseConvert.INSTANCE.entity2dto(po);
        resultDTO.setCharge(dto.getCharge());
        resultDTO.setPrice(dto.getPrice());
        return resultDTO;
    }
    @Transactional
    public void removeCourseBase(Long courseBaseId, Long companyId) {

        // 2.判断关键数据
        //      courseBaseId
        //      companyid
        if (ObjectUtils.isEmpty(courseBaseId) ||
                ObjectUtils.isEmpty(companyId)
        ) {
            ExceptionCast.cast(CommonErrorCode.E_100101);
        }

        //3.判断业务数据
        //     判断课程是否存在
        //     判断是否是同一家机构
        //     判断课程是否已经删除
        //     判断课程的审核状态
        //         未提交
        //         审核未通过
        //         只有这些状态才可以被删除
        getCourseByLogic(companyId, courseBaseId);


        // 4.删除课程基础信息（根据id删除）
        //     修改数据库的数据status
        // update course_base set status = ? where course_id = ?
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG.getCodeInt());
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());

        updateWrapper.eq(CourseBase::getId, courseBaseId);

        boolean result = update(updateWrapper);
        if (!result) {
            ExceptionCast.cast(ContentErrorCode.E_120017);
        }


    }
}




